/**************************************************************************************************
 * @file        os_allocator.h
 * @brief       跨平台自定义内存分配器封装，基于std::allocator实现
 * @details     提供带文件和行号追踪功能的自定义内存分配器，用于内存泄漏检测和调试
 *
 * @author      taoist.luo
 * @version     1.0.0
 * @date        2024-09
 *
 * Copyright (c) 2024 taoist.luo (https://gitee.com/harmonyluo(https://blog.csdn.net/harmonyluo))
 *
 * MIT License
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *************************************************************************************************/

#pragma once

#include <cstdlib>
#include <iostream>
#include <limits>

#include "memery/os_new.h"

/***************************************************************************
 * @brief 自定义内存分配器，用于替代标准库默认的allocator
 *
 * 该分配器使用重载的全局new/delete操作符来进行内存管理，
 * 可以与C++ STL容器配合使用，实现统一的内存管理策略。
 * @tparam T 分配的对象类型
 **************************************************************************/
template <typename T>
class os_allocator
{
public:
    // C++11 allocator typedefs
    typedef T value_type;
    typedef T* pointer;
    typedef const T* const_pointer;
    typedef T& reference;
    typedef const T& const_reference;
    typedef size_t size_type;
    typedef ptrdiff_t difference_type;

    /**************************************************************************
     * @brief 重新绑定到其他类型的分配器
     * @tparam U 其他类型
     **************************************************************************/
    template <typename U>
    struct rebind {
        typedef os_allocator<U> other;  ///< 绑定到类型U的分配器
    };

    /**************************************************************************
     * @brief 默认构造函数
     **************************************************************************/
    os_allocator() = delete;
    os_allocator(const char* file, int line) noexcept :
        m_file(file),
        m_line(line)
    {
    }
    void set_info(const char* file, int line)
    {
        m_file = file;
        m_line = line;
    }
    /**************************************************************************
     * @brief 拷贝构造函数模板
     * @tparam U 其他类型
     * @param 其他类型的分配器实例
     **************************************************************************/
    // 拷贝构造函数
    template <typename U>
    os_allocator(const os_allocator<U>& other) noexcept :
        m_file(other.m_file),
        m_line(other.m_line)
    {
    }

    /**************************************************************************
     * @brief 分配内存块
     * @param n 要分配的对象个数
     * @return 指向已分配内存的指针
     * @throws std::bad_alloc 内存分配失败时抛出异常
     **************************************************************************/
    T* allocate(size_t n)
    {
        if (n == 0) {
            return nullptr;
        }
        return static_cast<T*>(operator new(n * sizeof(T), m_file, m_line));
    }
    /*************************************************************************
     * @brief 释放内存块
     * @param ptr 指向要释放内存的指针
     * @param 忽略的参数（为了与标准allocator接口兼容）
     **************************************************************************/
    void deallocate(T* ptr, size_t)
    {
        operator delete(ptr);
    }
    /**************************************************************************
     * @brief 在已分配的内存上构造对象
     * @tparam U 对象类型
     * @tparam Args 构造函数参数类型包
     * @param ptr 指向已分配内存的指针
     * @param args 传递给构造函数的参数
     * 使用placement new（即new (ptr) U(...)）来在ptr指向的内存中构造U类型的对象。
     **************************************************************************/
    template <typename U, typename... Args>
    void construct(U* ptr, Args&&... args)
    {
        new (ptr) U(std::forward<Args>(args)...);
    }

    /**************************************************************************
     * @brief 销毁对象
     * @tparam U 对象类型
     * @param ptr 指向要销毁对象的指针
     **************************************************************************/
    template <typename U>
    void destroy(U* ptr)
    {
        ptr->~U();
    }

    /***************************************************************************
     * @brief 返回可分配的最大对象数量
     * @return 最大可分配对象数量
     **************************************************************************/
    size_t max_size() const noexcept
    {
        return std::numeric_limits<size_t>::max() / sizeof(T);
    }

    /***************************************************************************
     * @brief 判断两个分配器是否相等
     * @tparam U 其他类型
     * @return
     **************************************************************************/
    template <typename U>
    bool operator==(const os_allocator<U>& other) const noexcept
    {
        return (other.m_file == m_file) && (other.m_line == m_line);
    }

    /**************************************************************************
     * @brief 判断两个分配器是否不等
     * @tparam U 其他类型
     * @return
     **************************************************************************/
    template <typename U>
    bool operator!=(const os_allocator<U>& other) const noexcept
    {
        return (other.m_file != m_file) || (other.m_line != m_line);
    }

public:
    const char* m_file;
    const int m_line;
};
#define _INIT_ALLOCATOR_(T) (os_allocator<T>(__FILE__, __LINE__))